#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 30
#define Len 10
#define Course 6
//定义结构体
typedef struct student
{
    long num;
    char name[Len];
    int score[Course];
    int sum;
    float aver;
}STUDENT;

void PrintMenu(void);
void Input(STUDENT per[], int course_num, int n);
void Score_Course(STUDENT per[], int n, int course_num);
void Score_Student(STUDENT per[], int n);
int Score_Descend(int a, int b);
int Score_Ascend(int a, int b);
void Number_Ascend(STUDENT per[], int n);
void Name_Ascend(STUDENT per[], int n);
void SearchNum(STUDENT per[], int n, int course_num);
void SearchName(STUDENT per[], int n, int course_num);
void Statistic_Analysis(STUDENT per[], int n ,int course_num);
void SelectionSort(STUDENT per[], int n, int(*compare)(int a,int b));
void Swap(STUDENT *a, STUDENT *b);
void WritetoFile(STUDENT per[], int n, int course_num);
int ReadfromFile(STUDENT per[], int *p);
void Print_Table(STUDENT per[],int n ,int course_num);

int main()
{
    printf("Number:180110711\n");
    printf("subject No.9 - program No.1 V5.0\n\n");

    STUDENT per[N];//储存每位学生信息
    int course_num,n;
    int i;

    PrintMenu();

    //根据ret即用户选项执行操作
    for( ; i!=-1 ;)
    {
        printf("\nPlease enter your choice:");
        scanf("%d",&i);

        if(getchar()=='O')
        {
            i = -1;
        }

        switch(i)
        {
            case 1:
                do
                {
                    printf("please input the course amount and the amount of student as:NUM1 NUM2\n");
                    scanf("%d %d",&course_num,&n);
                }while(course_num>Course || n>N);//防止数据过大
                Input(per, course_num, n);
                break;
            case 2:
                Score_Course(per, n, course_num);
                break;
            case 3:
                Score_Student(per, n);
                break;
            case 4:
                SelectionSort(per, n, Score_Descend);
                Print_Table(per, n, course_num);
                break;
            case 5:
                SelectionSort(per, n, Score_Ascend);
                Print_Table(per, n, course_num);
                break;
            case 6:
                Number_Ascend(per, n);
                Print_Table(per, n, course_num);
                break;
            case 7:
                Name_Ascend(per, n);
                Print_Table(per, n, course_num);
                break;
            case 8:
                SelectionSort(per, n, Score_Descend);
                SearchNum(per, n, course_num);
                break;
            case 9:
                SelectionSort(per, n, Score_Descend);
                SearchName(per, n, course_num);
                break;
            case 10:
                Statistic_Analysis(per, n, course_num);
                break;
            case 11:
                Print_Table(per, n, course_num);
                Score_Course(per, n, course_num);
                break;
            case 12:
                WritetoFile(per, n, course_num);
                break;
            case 13:
                n = ReadfromFile(per, &course_num);
                Print_Table(per, n, course_num);
                break;
            case -1:
                break;
            default:
                printf("input error\n");
                break;
         }
    }
    return 0;
}

/*函数功能： 输出菜单；*/
void PrintMenu(void)
{
    printf("1.Input record\n");
    printf("2.Calculate total and average score of every course\n");
    printf("3.Calculate total and average score of every student\n");
    printf("4.Sort in descending order by total score of every student\n");
    printf("5.Sort in ascending order by total score of every student\n");
    printf("6.Sort in ascending order by number\n");
    printf("7.Sort in dictionary order by name\n");
    printf("8.Search by number\n");
    printf("9.Search by name\n");
    printf("10.Statistic analysis for every course\n");
    printf("11.List record\n");
    printf("12.Write to a file\n");
    printf("13.Read form a file\n");
    printf("O.Exit\n\n");
}

/*函数功能： 录入每个学生的学号，姓名和各科考试成绩；
  输入：     score,num，name数组分别存储考试成绩和学生学号，姓名；
             course_num，n为课程数和学生人数*/
void Input(STUDENT per[], int course_num, int n)
{
    int i,j;
    //数据初始化为0
    for(i=0 ; i<n ; i++)
    {
        per[i].sum = 0;
    }

    for(i=0 ; i<n ; i++)
    {
        printf("please input the record %d:\n",i+1);
        printf("please input the number:");
        scanf("%ld",&per[i].num);
        printf("please input the name:");
        scanf("%s",per[i].name);
        for(j=0 ; j<course_num ; j++)
        {
            //输入成绩并排错
            do
            {
                printf("please input the %d course score:",j+1);
                scanf("%d",&per[i].score[j]);
                if(per[i].score[j]<0  || per[i].score[j]>100)
                {
                    printf("input error please input again\n");
                }
            }while(per[i].score[j]<0 || per[i].score[j]>100);

            per[i].sum += per[i].score[j];
            per[i].aver = (float)per[i].sum/course_num;
        }
    }
}

/*函数功能：  计算并输出每门课程的总分和平均分；
  输入：      成绩数组score[][]，人数n,课程数course；*/
void Score_Course(STUDENT per[], int n, int course_num)
{
    int i,j;
    int sum;
    for(i=0 ; i<course_num ; i++)
    {
        for(sum=0,j=0 ; j<n ; j++)
        {
            sum += per[j].score[i];
        }
        printf("the total and average score of %4d course is %4d %4.2f\n",i+1,sum,(float)sum/n);
    }
}
/*函数功能：  计算并输出每位学生的总分和平均分；
  输入：      成绩数组score[][]，人数n,个人总分sum[i]；*/
void Score_Student(STUDENT per[], int n)
{
    int i;
    for(i=0 ; i<n ; i++)
    {
        printf("the total and average score of %ld is %4d %8.2f\n",per[i].num,per[i].sum,(float)per[i].aver);
    }
}

/*函数功能：  调用函数指针conpare实现对成绩的排序;
  输入：      总成绩sum[],对应学号num[]，总人数n；
  函数指针：  降序指向函数Score_Decend,升序指向Score_Ascend*/
void SelectionSort(STUDENT per[], int n, int (*compare)(int a,int b))
{
   int i,j,k;

    //交换算法排序；
   for (i=0 ; i<n-1 ; i++)
   {
       k = i;
       for(j=i+1 ; j<n ; j++)
       {
           if((*compare)(per[k].sum, per[j].sum))
           {
               k = j;
           }
       }
       if(k != i)
       {
           Swap(&per[i], &per[k]);
       }
   }
}
/*函数功能：  数据降序；
  输入：      数据a,b;
  函数返回值：判断a < b*/
int Score_Descend(int a, int b)
{
    return a < b;
}
/*函数功能：  数据升序；
  输入;       数据a,b;
  函数返回值：判断a>b*/
int Score_Ascend(int a, int b)
{
    return a > b;
}

/*函数功能：  按学号由小到大；
  输入：      成绩score[],对应学号num[]，总人数n；
  调用函数：  Print_Table*/
void Number_Ascend(STUDENT per[], int n)
{
    int i,j,k;

    //交换算法排序；
    for (i=0 ; i<n-1 ; i++)
    {
        k = i;
        for(j=i+1 ; j<n ; j++)
        {
            if(per[k].num > per[j].num)
            {
                k = j;
            }
        }
        if(k != i)
        {
            Swap(&per[i], &per[k]);
        }
    }
}
/*函数功能：  按姓名的字典顺序；
  输入：      成绩score[],对应学号num[]，总人数n；
  调用函数：  Print_Table*/
void Name_Ascend(STUDENT per[], int n)
{
    int i,j,k;

    //交换算法排序；
    for (i=0 ; i<n-1 ; i++)
    {
        k = i;
        for(j=i+1 ; j<n ; j++)
        {
            if(strcmp(per[j].name, per[k].name) <0)
            {
                k = j;
            }
        }
        if(k != i)
        {
            Swap(&per[i], &per[k]);
        }
    }
}

/*函数功能：  按学号查询学生排名及考试成绩；
  输入：      成绩score,学号num，总人数n；
  调用函数：  SelectionSort,Score_Descend*/
void SearchNum(STUDENT per[],int n, int course_num)
{
    long temp;
    int i,j;
    printf("Please input the student number:");
    scanf("%ld",&temp);
    getchar();
    //查找并打印
    for(i=0 ; i<n ; i++)
    {
        if(per[i].num == temp)
        {
            printf("the line is %d\n",i+1);
            for(j=0 ; j<course_num ; j++)
            {
                printf("the %d course:%d\n",j+1, per[i].score[j]);
            }
            break;
        }
    }
    //排错
    if(i == n)
    {
        printf("the input number is error\n");
    }
}
/*函数功能：  按姓名查询学生排名及考试成绩；
  输入：      成绩score，学号num，姓名name，人数n；；
  调用函数：  SelectionSort，Score_Descend*/
void SearchName(STUDENT per[],int n, int course_num)
{
    char temp[Len];
    int i,j;
    printf("Please input the student name:");
    gets(temp);

    for(i=0 ; i<n ; i++)
    {
        if(strcmp(per[i].name,temp) == 0)
        {
            printf("the line is %d\n",i+1);
            for(j=0 ; j<course_num ; j++)
            {
                printf("the %d course:%d\n",j+1,per[i].score[j]);
            }
            break;
        }
    }
    //排错
    if(i == n)
    {
        printf("the input name is error\n");
    }
}

/*函数功能：  统计五个类别的人数及所占百分比；
  输入：      成绩score,总人数n；*/
void Statistic_Analysis(STUDENT per[], int n, int course_num)
{
    int counts[5]={0};
    int i , m, j;
    for(j=0 ; j<course_num ; j++)
    {
        for(i=0 ; i<n ; i++)
        {
                m = per[i].score[j]/10;
                switch(m)
                {
                    case 10:
                    case 9:
                        counts[0]++;
                        break;
                    case 8:
                        counts[1]++;
                        break;
                    case 7:
                        counts[2]++;
                        break;
                    case 6:
                        counts[3]++;
                        break;
                    case 5:
                    case 4:
                    case 3:
                    case 2:
                    case 1:
                    case 0:
                        counts[4]++;
                        break;
                }
        }
        printf("the %4d course\n",j+1);
        printf("优秀人数   %d ,百分比%8.2f %% \n",counts[0],(float)counts[0]*100/n);
        printf("良好人数   %d ,百分比%8.2f %% \n",counts[1],(float)counts[1]*100/n);
        printf("中等人数   %d ,百分比%8.2f %% \n",counts[2],(float)counts[2]*100/n);
        printf("及格人数   %d ,百分比%8.2f %% \n",counts[3],(float)counts[3]*100/n);
        printf("不及格人数 %d ,百分比%8.2f %% \n",counts[4],(float)counts[4]*100/n);
    }

}

/*函数功能：  交换所有数据;*/
void Swap(STUDENT *a, STUDENT *b)
{
    STUDENT temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

/*函数功能：  打印学号以及对应成绩；
  输入：      成绩score，学号num,总人数n*/
void Print_Table(STUDENT per[],int n, int course_num)
{
    int i=0,j;

    //输出题头
    printf("the number the name ");
    for(i=0 ; i<course_num ; i++)
    {
        printf("the %d course ",i+1);
    }
    printf("the total the aver\n");

    //输出所有信息
    for(i=0 ; i<n ; i++)
    {
        printf("%5ld\t\t%s\t",per[i].num,per[i].name);
        for(j=0 ; j<course_num ; j++)
        {
            printf("%5d\t",per[i].score[j]);
        }
        printf("%5d\t%5.2f\t\n",per[i].sum,(float)per[i].aver);
    }
}

/*函数功能：  将学生数据写入文件；*/
void WritetoFile(STUDENT per[], int n, int course_num)
{
    FILE *fp;
    if((fp = fopen("student.txt","w")) == NULL)//只写
    {
        printf("Fail to open student.txt, fail to write data\n");
        exit(0);
    }
    fprintf(fp,"%d",course_num);
    fwrite(per, sizeof(STUDENT), n, fp);
    fclose(fp);
    printf("Success to write\n");
}

/*函数功能：  从文件中读取学生数据；*/
int ReadfromFile(STUDENT per[], int *p)
{
    FILE *fp;
    int i;
    if((fp = fopen("student.txt","r")) == NULL)//只读
    {
        printf("Fail to open the student.txt\n");
        exit(0);
    }
    fscanf(fp,"%d",p);
    for(i=0 ; !feof(fp) ; i++)
    {
        fread(&per[i], sizeof(STUDENT), 1, fp);
    }
    fclose(fp);
    printf("Success to read\n");
    return i-1;
}
